Source code

Under 100 files (54). Under 10k lines of code (7k). No comments (0). The code for the language server is built using the Xtext framework in Eclipse. It consists of two projects, m and m.ide. The project m holds all the information for running the compiler in headless mode. This includes the grammar specifying the lexer and parser rules, the validator, formatter, linker and code generators. In fact, m consists of multiple languages, one for each kind of supported file type. Currently, there is a language for JSON, XML, YAML, C#, and of course M and all its variants in different natural languages. Every component of the language is wired up using Google's Guice dependency injection framework. The IDE components like code completion, syntax highlighting, labels, quick fixes, outline view are coded in the m.ide project independently from the execution platform. It is useful to have an additional m.ui project to test the functionality ina eclipse instance with a debugger attached to it.

Single sourcing: If certain code's structure logically depends on another code, it should get autogenerated. Example: Blockly block definitions depend on the grammars rules. Block definition files are automatically generated based on the grammars.

plugin.xml: Needs to be updated every time a new language is added/removed. Use plugin.xml_gen src-gen, xtend-gen: Automatically generated, need to be added to the build path.

Parser: Terminals are single character and pairwise disjoint. Dont use hidden terminals. Dont use until token. Dont use syntactic predicates. Dont use backtracking. DataTypes combine terminals in the least information needed. Expressions follow Xtext guidelines for associativity and precedence. Full support for c# expressions in the base grammar. M grammar can override a rule to skip certain operators from the language. Unary minus operand acts on floats to make them negative (otherwise they are alway positive). Numbers in components can be negative because they use a different datatype rule which can include a minus sign (NUMBER vs FLOAT).

m/src

xRuntimeModule: Dependency injection wiring via Google guice modules. If the injection is already wired in AbstractLanguageRuntimeModule, the injection needs to be overridden, if it is not it must be defined. Xtext has syntax sugar def bindIService(){ ClassName } OutputConfiguration is an example.

x.xtext: Grammar definitions. All independent. Few terminals. More data rules and finally parser rules. no backtracking, no semantic helpers.

converter/MyTerminalConverter: Used when terminal rules are intended to return something other than a EString. Defines how the conversion works in both directions.

errorHandling/XSyntaxErrorMessageProvider: Used when the parser throws an error to improve the error message considering the context.

xFormatter: dispatched functions to add white spaces when serializing a model. AAlways try to use prepend to avoid conflicts, use grammar access to access non-keywords. Use literal keywords like ',' instead of grammarAccess ones for better maintainability.

LanguageGenerator:

Main.java: For headless execution. Only need java JRE and the JAR built. Give it a file and it will parse it and generate it for you.

transformation: Each file is responsible of generating all files of a specific kind. First the type inference is run and now with the model and the types inferred all the artifacts can be generated. BuiltInLibrary translates names of built-in components for generating the same text in other languages. Some are legacy code. Only the ones that uses TextGenerator matter.

No hybrid or pure distinction, use Hybrid.Rendering, Unity.Physics etc when they are ready and do the rest in Hybrid, as any professional would do nowadays.

UnityGenerator UnityParser BlockGenerator BlockParser

xValidator: Rules to make extra assumptions true in the model. For example unique names.

Workflow.mwe2: Very important. Generates all the artifacts. It defines the project structure and the fragments that each language cares about.

ide:

MyContentAssist extends IdeContentProposalProvider: For platform agnostic definition of content assist proposals.

MyLabelProvider extends SimpleNameLabelProvider: For platform agnostic definition of label names.

build.gradle: Gradle script to build the language server. It needs the reference to the mwe workflow file and it passes it the rootPath variable. It runs the workflow and generates a language server fat jar file in build folder.